package com.newshub.monitor.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.newshub.monitor.config.MonitorProperties;
import com.newshub.monitor.service.MonitorOverviewService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.file.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 监控概览服务实现类
 */
@Slf4j
@Service
public class MonitorOverviewServiceImpl implements MonitorOverviewService {

    private final ObjectMapper objectMapper = new ObjectMapper();
    
    @Autowired
    private MonitorProperties monitorProperties;

    @Override
    public Map<String, Object> getSystemOverview() {
        try {
            String logFile = getTodayLogFile();
            List<JsonNode> logs = readLogFile(logFile);
            
            Map<String, Object> overview = new HashMap<>();
            
            // 基础统计
            long totalRequests = logs.stream()
                .filter(log -> "方法开始执行".equals(log.path("message").asText()))
                .count();
                
            long successRequests = logs.stream()
                .filter(log -> "方法执行成功".equals(log.path("message").asText()))
                .count();
                
            long errorRequests = logs.stream()
                .filter(log -> "ERROR".equals(log.path("level").asText()))
                .count();
            
            // 性能统计
            List<Long> executionTimes = logs.stream()
                .filter(log -> log.has("executionTime") && !log.path("executionTime").isNull())
                .map(log -> log.path("executionTime").asLong())
                .collect(Collectors.toList());
            
            double avgExecutionTime = executionTimes.stream()
                .mapToLong(Long::longValue)
                .average()
                .orElse(0.0);
                
            long maxExecutionTime = executionTimes.stream()
                .mapToLong(Long::longValue)
                .max()
                .orElse(0);
                
            long slowQueries = executionTimes.stream()
                .filter(time -> time > 100)
                .count();
            
            overview.put("totalRequests", totalRequests);
            overview.put("successRequests", successRequests);
            overview.put("errorRequests", errorRequests);
            overview.put("successRate", totalRequests > 0 ? (double) successRequests / totalRequests * 100 : 0);
            overview.put("avgExecutionTime", Math.round(avgExecutionTime * 100.0) / 100.0);
            overview.put("maxExecutionTime", maxExecutionTime);
            overview.put("slowQueries", slowQueries);
            overview.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            
            return overview;
            
        } catch (Exception e) {
            log.error("获取系统概览失败", e);
            throw new RuntimeException("获取系统概览失败: " + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> getPerformanceTrend(LocalDateTime startTime, LocalDateTime endTime, String interval) {
        try {
            String logFile = getTodayLogFile();
            List<JsonNode> logs = readLogFile(logFile);
            
            Map<String, Object> trend = new HashMap<>();
            
            // 按时间间隔分组统计
            Map<String, List<Long>> timeGroups = new HashMap<>();
            
            logs.stream()
                .filter(log -> log.has("executionTime") && !log.path("executionTime").isNull())
                .forEach(log -> {
                    String timestamp = log.path("timestamp").asText();
                    long executionTime = log.path("executionTime").asLong();
                    
                    String timeKey = getTimeKey(timestamp, interval);
                    timeGroups.computeIfAbsent(timeKey, k -> new ArrayList<>()).add(executionTime);
                });
            
            // 计算每个时间段的统计信息
            List<Map<String, Object>> trendData = timeGroups.entrySet().stream()
                .map(entry -> {
                    String timeKey = entry.getKey();
                    List<Long> times = entry.getValue();
                    
                    Map<String, Object> timeStats = new HashMap<>();
                    timeStats.put("time", timeKey);
                    timeStats.put("avgTime", Math.round(times.stream().mapToLong(Long::longValue).average().orElse(0) * 100.0) / 100.0);
                    timeStats.put("maxTime", times.stream().mapToLong(Long::longValue).max().orElse(0));
                    timeStats.put("count", times.size());
                    
                    return timeStats;
                })
                .sorted((a, b) -> ((String) a.get("time")).compareTo((String) b.get("time")))
                .collect(Collectors.toList());
            
            trend.put("trendData", trendData);
            trend.put("interval", interval);
            
            return trend;
            
        } catch (Exception e) {
            log.error("获取性能趋势失败", e);
            throw new RuntimeException("获取性能趋势失败: " + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> getMethodRanking(Integer limit, LocalDateTime startTime, LocalDateTime endTime) {
        try {
            String logFile = getTodayLogFile();
            List<JsonNode> logs = readLogFile(logFile);
            
            // 按方法名分组统计
            Map<String, List<Long>> methodTimes = new HashMap<>();
            
            logs.stream()
                .filter(log -> log.has("executionTime") && !log.path("executionTime").isNull())
                .forEach(log -> {
                    String methodName = log.path("methodName").asText();
                    long executionTime = log.path("executionTime").asLong();
                    
                    methodTimes.computeIfAbsent(methodName, k -> new ArrayList<>()).add(executionTime);
                });
            
            // 计算每个方法的统计信息
            List<Map<String, Object>> ranking = methodTimes.entrySet().stream()
                .map(entry -> {
                    String methodName = entry.getKey();
                    List<Long> times = entry.getValue();
                    
                    Map<String, Object> methodStats = new HashMap<>();
                    methodStats.put("methodName", methodName);
                    methodStats.put("callCount", times.size());
                    methodStats.put("avgTime", Math.round(times.stream().mapToLong(Long::longValue).average().orElse(0) * 100.0) / 100.0);
                    methodStats.put("minTime", times.stream().mapToLong(Long::longValue).min().orElse(0));
                    methodStats.put("maxTime", times.stream().mapToLong(Long::longValue).max().orElse(0));
                    methodStats.put("totalTime", times.stream().mapToLong(Long::longValue).sum());
                    
                    return methodStats;
                })
                .sorted((a, b) -> Double.compare((Double) b.get("avgTime"), (Double) a.get("avgTime")))
                .limit(limit)
                .collect(Collectors.toList());
            
            Map<String, Object> result = new HashMap<>();
            result.put("ranking", ranking);
            result.put("total", methodTimes.size());
            
            return result;
            
        } catch (Exception e) {
            log.error("获取方法排行失败", e);
            throw new RuntimeException("获取方法排行失败: " + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> getSystemStatus() {
        try {
            Map<String, Object> status = new HashMap<>();
            
            // 系统运行状态
            status.put("systemRunning", true);
            status.put("logRecording", true);
            status.put("monitorActive", true);
            
            // 服务状态
            Map<String, Object> services = new HashMap<>();
            services.put("database", "正常");
            services.put("cache", "正常");
            services.put("fileSystem", "正常");
            services.put("network", "正常");
            status.put("services", services);
            
            // 资源使用情况
            Runtime runtime = Runtime.getRuntime();
            long totalMemory = runtime.totalMemory();
            long freeMemory = runtime.freeMemory();
            long usedMemory = totalMemory - freeMemory;
            
            Map<String, Object> resources = new HashMap<>();
            resources.put("memoryUsage", Math.round((double) usedMemory / totalMemory * 100));
            resources.put("totalMemory", totalMemory);
            resources.put("usedMemory", usedMemory);
            resources.put("freeMemory", freeMemory);
            status.put("resources", resources);
            
            status.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            
            return status;
            
        } catch (Exception e) {
            log.error("获取系统状态失败", e);
            throw new RuntimeException("获取系统状态失败: " + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> getRealtimeMetrics() {
        try {
            Map<String, Object> metrics = new HashMap<>();
            
            // 获取最近的日志数据
            String logFile = getTodayLogFile();
            List<JsonNode> logs = readLogFile(logFile);
            
            // 最近5分钟的请求统计
            LocalDateTime fiveMinutesAgo = LocalDateTime.now().minusMinutes(5);
            long recentRequests = logs.stream()
                .filter(log -> {
                    String timestamp = log.path("timestamp").asText();
                    try {
                        LocalDateTime logTime = LocalDateTime.parse(timestamp.substring(0, 19));
                        return logTime.isAfter(fiveMinutesAgo) && "方法开始执行".equals(log.path("message").asText());
                    } catch (Exception e) {
                        return false;
                    }
                })
                .count();
            
            metrics.put("recentRequests", recentRequests);
            metrics.put("requestsPerMinute", Math.round((double) recentRequests / 5));
            metrics.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            
            return metrics;
            
        } catch (Exception e) {
            log.error("获取实时监控数据失败", e);
            throw new RuntimeException("获取实时监控数据失败: " + e.getMessage());
        }
    }

    /**
     * 读取日志文件
     */
    private List<JsonNode> readLogFile(String logFile) throws IOException {
        List<JsonNode> logs = new ArrayList<>();
        
        if (!Files.exists(Paths.get(logFile))) {
            return logs;
        }
        
        try (BufferedReader reader = Files.newBufferedReader(Paths.get(logFile))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.trim().isEmpty()) continue;
                
                try {
                    JsonNode logEntry = objectMapper.readTree(line);
                    logs.add(logEntry);
                } catch (Exception e) {
                    continue;
                }
            }
        }
        
        return logs;
    }

    /**
     * 获取今日日志文件路径
     */
    private String getTodayLogFile() {
        return monitorProperties.getTodayLogFilePath();
    }

    /**
     * 根据时间间隔获取时间键
     */
    private String getTimeKey(String timestamp, String interval) {
        try {
            LocalDateTime dateTime = LocalDateTime.parse(timestamp.substring(0, 19));
            
            switch (interval) {
                case "1h":
                    return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00"));
                case "30m":
                case "15m":
                case "5m":
                    return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
                default:
                    return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00"));
            }
        } catch (Exception e) {
            return "unknown";
        }
    }
}
